// Agent jasim in project Jasim
{ include("jasim-event.asl")}

/* Initial beliefs and rules */
known_agents(0).

can_combines_and(G, G1, G2):- plan(combinesand2(G, G1, G2)) & fulfilled(G2).
can_combines_and(G, G1, G2):- plan(combinesand2(G, G2, G1)) & fulfilled(G2).

can_combines_and(G, G1, G2, G3):- plan(combinesand3(G, G1, G2, G3)) & fulfilled(G2) & fulfilled(G3).
can_combines_and(G, G1, G2, G3):- plan(combinesand3(G, G2, G1, G3)) & fulfilled(G2) & fulfilled(G3).
can_combines_and(G, G1, G2, G3):- plan(combinesand3(G, G2, G3, G1)) & fulfilled(G2) & fulfilled(G3).

/* Initial goals */

!start.

/* Plans */

+!start : true <-
	-+known_agents(0);
	
	start_planer;
	introduce_agents;
	.broadcast(achieve, start).

// triggered by an agent when it have just joint into the world
@welcome_agent[atomic]
+!welcome(A): true
	<-
	?known_agents(X);
	N = X + 1;
	-+known_agents(N).

+!check_replan(L): true
	<-
	!restart.

+force_restart[source(percept)]: true
	<-
	remove_percept(force_restart);
	!restart.

+!restart : known_agents(N) & .count(ready(_), N)
	<-
	.abolish(ready(_));
	!start.

+!restart : true
	<-
	.broadcast(achieve, restart).

@r[atomic]
+ready(A)[source(S)]: known_agents(N) & .count(ready(_), N)
	<-
	!restart.

@ready[atomic]
+ready(A): true
	<-
	.count(ready(_), Ready);
	?known_agents(N);
	.print(A, " is ready to restart. ", N - Ready, " left.").

/*------------------Goal Combination Plan---------------------------*/
+fulfilled(G1): can_combines_and(G, G1, G2) 
	<-
	.print(G, " is fulfilled by achieving ", G1, " and ", G2);
	.broadcast(tell, fulfilled(G)); 
	+fulfilled(G).

+fulfilled(G1): can_combines_and(G, G1, G2, G3)
	<-
	.print(G, ": is fulfilled by achieving ", G1, " and ", G2, " and ", G3);
	.broadcast(tell, fulfilled(G)); 
	+fulfilled(G).

// combinesor2
+fulfilled(G1): (combinesor2(G, G1, G2) | combinesor2(G, G2, G1))
	<- 
	.print(G, "is fulfilled by achieving either ", G1, " or ", G2);
	.broadcast(tell, fulfilled(G));
	+fulfilled(G).

+fulfilled(G1): (combinesor3(G, G1, G2, G3) | combinesor3(G, G2, G1, G3) | combinesor3(G, G2, G3, G1))
	<- 
	.print(G, "is fulfilled by achieving either ", G1, " or ", G2, " or ", G3);
	.broadcast(tell, fulfilled(G));
	+fulfilled(G).
